import Monster from "../Monster/Monster";
import gTipManager from "../TipManager";
import Player from "../Player/Player";
import PlayerView from "./PlayerView";

const { ccclass, property } = cc._decorator;

@ccclass
export default class MonsterView extends cc.Component {

    @property
    speed: number = 100;

    body: cc.RigidBody = null;

    //是否正在移动
    is_moving: boolean = false;
    //当前需要移动的总时间
    move_time: number = 0;
    //x方向速度
    vx: number = 0;
    //y方向速度
    vy: number = 0;
    //是否初始化完成
    inited: boolean = false;

    m_monster: Monster = null;
    anim: cc.Animation = null;
    dir: number = 0;
    state: string = "";
    //是否开始战斗
    is_atk: boolean = false;
    atk_player: Player = null;

    onLoad() {
        this.body = this.node.getComponent(cc.RigidBody);
        this.anim = this.node.getComponent(cc.Animation);
    }

    init(monster: Monster) {
        if (!monster || this.m_monster && this.m_monster.m_id == monster.m_id) {
            return;
        }
        this.reset();

        this.m_monster = monster;
        monster.m_monsterView = this;

        let resName = `animation/monster_${this.m_monster.m_id}`;
        cc.resources.loadDir(resName, cc.AnimationClip, (err, asset) => {
            if (!err) {
                asset.forEach((val, key) => {
                    let clip = <cc.AnimationClip>val;
                    this.anim.addClip(clip);
                    clip.addRef();
                });
                this.inited = true;
                this.updateAnim("run", 1);
                this.startRandoMove();
            }
        });
    }

    reset(){
        this.anim.stop();
        let clips = this.anim.getClips();
        for(let i = clips.length-1; i >= 0; --i){
            this.anim.removeClip(clips[i]);
        }

        this.move_time = 0;
        this.m_monster = null;
        this.dir = 0;
        this.state = "";
    }

    attack(){
        if(this.atk_player){
            this.m_monster.attack(this.atk_player);
        }
    }

    public startAttack():void{
        if(this.is_atk){
            return;
        }
        this.schedule(this.attack, 0.5);
        this.is_atk = true;
    }

    public stopAttack():void{
        this.unschedule(this.attack);
        this.is_atk = false;
    }

    onDead(){
        this.unscheduleAllCallbacks();
        this.inited = false;
    }

    onCollisionEnter(other: cc.Collider, self: cc.Collider){
        if(!this.inited){
            return;
        }

        let playerView = other.node.parent.getComponent(PlayerView);
        if(playerView){
            //暂停随机移动
            this.unschedule(this.randomMove);
            //切换攻击动画
            let dir = other.node.parent.x > self.node.x ? 7 : 3;
            this.updateAnim("attack", dir);
            this.atk_player = playerView.m_player;
            this.startAttack();
        }
    }

    onCollisionExit(other: cc.Collider, self: cc.Collider){
        if(!this.inited){
            return;
        }

        //恢复原地动画
        this.updateAnim("run", this.dir);
        //恢复随机移动
        this.startRandoMove();

        this.stopAttack();
    }

    onAttack(hp:number){
        //被攻击后损失的hp
        //let w_pos = this.node.convertToWorldSpaceAR(this.node.getPosition());
        gTipManager.instance().showTip(`-${hp}`, cc.Color.RED, this.node);
    }

    startRandoMove(){
        this.unschedule(this.randomMove);
        this.schedule(this.randomMove, 10);
    }

    randomMove():void{

        //获取当前坐标
        let curPos: cc.Vec2 = this.node.getPosition();
        let rVal = Math.ceil(Math.random() * 300);
        rVal = Math.random() > 0.5 ? -rVal : rVal;
        if(rVal % 2 == 0){
            curPos.x += rVal;
        }
        else{
            curPos.y += rVal;
        }

        //限制用户移动在地图内
        let size = this.node.parent.getContentSize();
        let maxH = size.height / 2 - 30;
        let maxW = size.width / 2 - 30;
        curPos.x = Math.abs(curPos.x) > maxW ? (curPos.x > 0 ? maxW : -maxW) : curPos.x;
        curPos.y = Math.abs(curPos.y) > maxH ? (curPos.y > 0 ? maxH : -maxH) : curPos.y;

        this.moveToDst(curPos);
    }

    moveToDst(dst: cc.Vec2){
        let src = this.node.getPosition();
        let dir = dst.sub(src);
        let len = dir.mag();
        if(len <= 0){
            return;
        }

        //时间=路程/速度
        this.move_time = len / this.speed;

        //x速度=x长度/时间
        this.vx = dir.x / this.move_time
        //y速度=y长度/时间
        this.vy = dir.y / this.move_time;

        this.body.linearVelocity = cc.v2(this.vx, this.vy);

        //计算移动方向
        let radian = cc.v2(dir).signAngle(cc.v2(0, -1));
        let degree = Math.floor(cc.misc.radiansToDegrees(radian));
        //console.log("degree:", degree, Math.round(degree / 45));
        let d = degree == 0 ? 0 : Math.round(degree / 45);
        d = d < 0 ? 8 + d + 1 : d + 1;
        //开始播放相应奔跑动画
        this.updateAnim("run", d);

        this.is_moving = true;
    }

    //刷新动画
    updateAnim(state: string, dir: number){
        if(this.dir === dir && this.state == state){
            return;
        }
        this.dir = dir;
        this.state = state;

        let realDir = dir;
        if(dir == 3){
            realDir = 7;
        }
        this.node.scaleX = dir == 3 ? -1 : 1;

        let animName = `monster_${this.m_monster.m_id}_${this.state}_${realDir}`;
        let animState = this.anim.play(animName);
        animState.wrapMode = cc.WrapMode.Loop;
        if(state == "run"){
            animState.speed = this.speed / 100;
        }
    }

    update(dt){
        if(!this.is_moving){
            return;
        }
        if(this.move_time <= 0){
            this.body.linearVelocity = cc.v2(0,0);
            //停止奔跑动画，播放原地动画
            this.updateAnim("run", this.dir);
            this.is_moving = false;
            return;
        }

        if(this.move_time < dt){
            //最后那一段需要重新计算
            this.vx *= this.move_time / dt;
            this.vy *= this.move_time / dt;
            this.body.linearVelocity = cc.v2(this.vx, this.vy);
        }

        this.move_time -= dt;
    }
}
